package org.tomac.io.fix;

import java.io.IOException;
import java.net.MalformedURLException;

import org.apache.log4j.Logger;
import org.tomac.io.IIOPlexor;
import org.tomac.protocol.fix.messaging.FixLogon;

public class FixInitiator extends FixSessionBase implements IFixSession {

	private static Logger log = Logger.getLogger(FixInitiator.class.getSimpleName());

	public FixInitiator(IIOPlexor plex, IFixURL url, IFixApplication application) {
		super(plex, url, application);
		out = new InititatorOutboundFixMessageListener();
	}
	
	@Override
	public void connect() throws IOException {

		if (log.isDebugEnabled()) log.debug("connecting to: " + url.getIpAddress());

		connection = plex.createClientConnection(url.getIpAddress());
		//should this be done in a separate start call?
		connection.addConnectionListener(this);
		connection.connect();
		setFixSessionState(FixSessionState.INITITATE_CONNECTION);
	}
	
	@Override
	public void onConnect() {
		
		setFixSessionState(FixSessionState.NETWORK_CONNECTION_ESTABLISHED);
		
		try {
			outboundLogHandle = plex.createLog(url.getOutboundFixLog());

			if (log.isDebugEnabled()) log.debug("created outbound log file: " + url.getOutboundFixLog());

			if (Boolean.getBoolean("fix.loginbound")) 
				inboundLogHandle = plex.createLog(url.getInboundFixLog());

			if (log.isDebugEnabled()) log.debug("created outbound log file: " + url.getInboundFixLog());
			// tell the application layer
			app.onConnect();

			FixLogon logon = createLogon();
			out.onFixLogon(logon);
		} catch (MalformedURLException e) {
			connection.close();
			log.error(e.getMessage(), e);
		} catch (IOException e) {
			connection.close();
			if (log.isDebugEnabled())
				log.error(e.getMessage(), e);
			else 
				log.error(e.getMessage());
		}
			
	}	
	
	@Override
	public void onFixLogon(FixLogon msg) {
		if (!msg.resetSeqNumFlag && msg.msgSeqNum < inMsgSeqNum + 1) {
			setFixSessionState(FixSessionState.INITIATE_LOGOUT_PROCESS); 
			out.onFixLogout(createLogout(("MsgSeqNum too low, expecting " + (inMsgSeqNum+1) + " but received " + msg.msgSeqNum).getBytes()));
			return;
		} 
		incrementInMsgSeqNum();
		disconnectNoLogonTimerInstance.cancel(disconnectNoLogonTimerTask);
		setFixSessionState(FixSessionState.ACTIVE);
		if (msg.resetSeqNumFlag) { 
			outMsgSeqNum = (int) msg.msgSeqNum - 1; // as it will be incremented upon send
			inMsgSeqNum = (int) msg.msgSeqNum;
		}
	}	
	
	public class InititatorOutboundFixMessageListener extends OutboundFixMessageListener {

		@Override
		public void onFixLogon(FixLogon msg) {
			send(msg);
			setFixSessionState(FixSessionState.INITIATION_LOGON_SENT);
			disconnectNoLogonTimerInstance = plex.scheduleTimer(disconnectNoLogonTimerTask, url.getHeartBtInt());
			
		}

	}	

}
